package mwt.xml.waxdbforms.business.impl;

import java.io.IOException;
import java.sql.SQLException;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.xpath.XPathExpressionException;
import mwt.xml.waxdbforms.business.DbmsService;
import mwt.xml.waxdbforms.business.exceptions.BusinessException;
import mwt.xml.xdbforms.dbms.XDBFManager;
import mwt.xml.xdbforms.dbms.exceptions.TypeNotFoundException;
import mwt.xml.xdbforms.dbms.metadata.MetadataManager;
import mwt.xml.xdbforms.dbms.metadata.impl.PrimaryKeyMetadata;
import mwt.xml.xdbforms.dbms.metadata.impl.TableMetadata;
import org.w3c.dom.Document;
import org.xml.sax.SAXException;

public class DbmsServiceImpl implements DbmsService {
    private XDBFManager xdbfm = null;

    public DbmsServiceImpl(XDBFManager xdbfm) {
        this.xdbfm = xdbfm;
    }

    public List<String> getSchemasList() throws BusinessException {
        MetadataManager mtdMngr = this.xdbfm.getMetadataManager();
        List<String> schemas = null;

        try {
            schemas = mtdMngr.getSchemasList();
        } catch (SQLException ex) {
            Logger.getLogger(DbmsServiceImpl.class.getName()).log(Level.SEVERE, null, ex);
            throw new BusinessException("Errore nel recupero della lista degli schemi dal database", ex);
        }

        return schemas;
    }
    
    public List<TableMetadata> getTablesList(String schemaName) throws BusinessException {
        MetadataManager mtdMngr = this.xdbfm.getMetadataManager();
        List<TableMetadata> tables = null;

        try {
            tables = mtdMngr.getTableList(schemaName);
        } catch (SQLException ex) {
            Logger.getLogger(DbmsServiceImpl.class.getName()).log(Level.SEVERE, null, ex);
            throw new BusinessException("Errore nel recupero della lista delle tabelle del database", ex);
        }

        return tables;
    }

    public TableMetadata getTbaleMetadata(String schemaName, String tableName) throws BusinessException {
        MetadataManager mtdMngr = this.xdbfm.getMetadataManager();
        TableMetadata tmd = null;
        
        try {
            tmd = mtdMngr.getTableMetadata(schemaName, tableName);
        } catch (SQLException ex) {
            Logger.getLogger(DbmsServiceImpl.class.getName()).log(Level.SEVERE, null, ex);
            throw new BusinessException("Errore nel recupero dei metadati della tabella", ex);
        }

        return tmd;
    }

    public Set<List<String>> getTableData(String schemaName, String tableName) throws BusinessException {
        try {
            return this.xdbfm.getQueryManager().load(schemaName, tableName);
        } catch (SQLException ex) {
            Logger.getLogger(DbmsServiceImpl.class.getName()).log(Level.SEVERE, null, ex);
            throw new BusinessException("Errore nel recupero del contenuto della tabella", ex);
        }
    }

    public String getXFormsModel(TableMetadata table, String action) throws BusinessException {
        try {
           return this.xdbfm.getXFormsModelManager().getModelAsString(table, action);
        } catch (ParserConfigurationException ex) {
            Logger.getLogger(DbmsServiceImpl.class.getName()).log(Level.SEVERE, null, ex);
            throw new BusinessException("Errore nella creazione del modello per xforms", ex);
        } catch (TypeNotFoundException ex) {
            Logger.getLogger(DbmsServiceImpl.class.getName()).log(Level.SEVERE, null, ex);
            throw new BusinessException("Errore nella creazione del modello per xforms", ex);
        }
    }

    public String getXFormsModel(TableMetadata table, String action, String pkValue) throws BusinessException {
        try {
            Iterator<PrimaryKeyMetadata> it = table.getPks().iterator();
            PrimaryKeyMetadata pk = it.next();

            Map<String, String> row = this.xdbfm.getQueryManager().getRow(table.getSchemaName(), table.getName(), pk.getColumnName(),pkValue);
            return this.xdbfm.getXFormsModelManager().getModelAsString(table, action, row);
        } catch (ParserConfigurationException ex) {
            Logger.getLogger(DbmsServiceImpl.class.getName()).log(Level.SEVERE, null, ex);
            throw new BusinessException("Errore nella creazione del modello per xforms", ex);
        } catch (TypeNotFoundException ex) {
            Logger.getLogger(DbmsServiceImpl.class.getName()).log(Level.SEVERE, null, ex);
            throw new BusinessException("Errore nella creazione del modello per xforms", ex);
        } catch (SQLException ex) {
            Logger.getLogger(DbmsServiceImpl.class.getName()).log(Level.SEVERE, null, ex);
            throw new BusinessException("Errore nella creazione del modello per xforms", ex);
        }
    }

    public Document getXFormsModelDoc(TableMetadata table, String action) throws BusinessException {
        try {
           return this.xdbfm.getXFormsModelManager().getModelAsDocument(table, action);
        } catch (ParserConfigurationException ex) {
            Logger.getLogger(DbmsServiceImpl.class.getName()).log(Level.SEVERE, null, ex);
            throw new BusinessException("Errore nella creazione del modello per xforms", ex);
        } catch (TypeNotFoundException ex) {
            Logger.getLogger(DbmsServiceImpl.class.getName()).log(Level.SEVERE, null, ex);
            throw new BusinessException("Errore nella creazione del modello per xforms", ex);
        }
    }

    public String getXFormsUI(TableMetadata table) throws BusinessException {
        try {
            return this.xdbfm.getXFormsUIManager().getUIAsString(table);
        } catch (ParserConfigurationException ex) {
            Logger.getLogger(DbmsServiceImpl.class.getName()).log(Level.SEVERE, null, ex);
            throw new BusinessException("Errore nella creazione della UI per xforms", ex);
        } catch (TypeNotFoundException ex) {
            Logger.getLogger(DbmsServiceImpl.class.getName()).log(Level.SEVERE, null, ex);
            throw new BusinessException("Errore nella creazione della UI per xforms", ex);
        }
    }

    public boolean insertTable(String xmlData) throws BusinessException {
        try {
            return this.xdbfm.getQueryManager().insert(xmlData);
        } catch (SQLException ex) {
            Logger.getLogger(DbmsServiceImpl.class.getName()).log(Level.SEVERE, null, ex);
            throw new BusinessException("Errore durante il salvataggio dei dati", ex);
        } catch (ParserConfigurationException ex) {
            Logger.getLogger(DbmsServiceImpl.class.getName()).log(Level.SEVERE, null, ex);
            throw new BusinessException("Errore durante il salvataggio dei dati", ex);
        } catch (SAXException ex) {
            Logger.getLogger(DbmsServiceImpl.class.getName()).log(Level.SEVERE, null, ex);
            throw new BusinessException("Errore durante il salvataggio dei dati", ex);
        } catch (IOException ex) {
            Logger.getLogger(DbmsServiceImpl.class.getName()).log(Level.SEVERE, null, ex);
            throw new BusinessException("Errore durante il salvataggio dei dati", ex);
        }
    }

    public void updateTable(String xmlData) throws BusinessException {
        try {
            this.xdbfm.getQueryManager().update(xmlData);
        } catch (SQLException ex) {
            Logger.getLogger(DbmsServiceImpl.class.getName()).log(Level.SEVERE, null, ex);
            throw new BusinessException("Errore durante l'aggiornamento dei dati", ex);
        } catch (ParserConfigurationException ex) {
            Logger.getLogger(DbmsServiceImpl.class.getName()).log(Level.SEVERE, null, ex);
            throw new BusinessException("Errore durante l'aggiornamento dei dati", ex);
        } catch (SAXException ex) {
            Logger.getLogger(DbmsServiceImpl.class.getName()).log(Level.SEVERE, null, ex);
            throw new BusinessException("Errore durante l'aggiornamento dei dati", ex);
        } catch (IOException ex) {
            Logger.getLogger(DbmsServiceImpl.class.getName()).log(Level.SEVERE, null, ex);
            throw new BusinessException("Errore durante l'aggiornamento dei dati", ex);
        } catch (XPathExpressionException ex) {
            Logger.getLogger(DbmsServiceImpl.class.getName()).log(Level.SEVERE, null, ex);
            throw new BusinessException("Errore durante l'aggiornamento dei dati", ex);
        }
        
    }

    public void deleteRow(TableMetadata table, String pkValue) throws BusinessException {
        try {
            Iterator<PrimaryKeyMetadata> it = table.getPks().iterator();
            PrimaryKeyMetadata pk = it.next();

            this.xdbfm.getQueryManager().deleteRow(table.getSchemaName(), table.getName(), pk.getColumnName(),pkValue);
        } catch (SQLException ex) {
            Logger.getLogger(DbmsServiceImpl.class.getName()).log(Level.SEVERE, null, ex);
            throw new BusinessException("Errore nella creazione del modello per xforms", ex);
        }
    }
}
